using Engine.FileFormats3D.WR2TrafficFiles;
using Engine.Graphics;
using Engine.TrafficHelpers;
using System.IO;

namespace street
{
    public struct PropertiesCR //Properties for crossroads
    {
        #region Private Fields

        private const byte VERSION = 0x03;// 16.10.2016

        private IMaterial materialForRail;
        private IMaterial materialForRoad;
        private int railLeft;
        private int raiRight;
        private float streetwidth;
        private CrossroadTraffic traffic;

        #endregion Private Fields

        #region Public Properties

        public IMaterial MaterialForRail
        {
            get { return materialForRail; }
            set { materialForRail = value; }
        }

        public IMaterial MaterialForRoad
        {
            get { return materialForRoad; }
            set { materialForRoad = value; }
        }

        public int RailLeft { get { return railLeft; } set { railLeft = value; } }

        public int RaiRight { get { return raiRight; } set { raiRight = value; } }

        public float Streetwidth
        {
            get
            {
                return streetwidth;
            }
            set
            {
                streetwidth = value;
            }
        }

        public CrossroadTraffic Traffic
        {
            get { return traffic; }
            set { traffic = value; }
        }

        #endregion Public Properties

        #region Internal Methods

        internal static PropertiesCR FromStream(BinaryReader br, Engine.AddinManager.IAddin gameDll, MaterialManager materialManager)
        {
            PropertiesCR pc = new PropertiesCR();
            byte version = br.ReadByte();
            switch (version)
            {
                case 0x01:
                    pc = LoadV1(br, gameDll, materialManager);
                    break;

                case 0x02:
                    pc = LoadV2(br, gameDll, materialManager);
                    break;

                case 0x03:
                    pc = LoadV3(br, gameDll, materialManager);
                    break;

                default:
                    br.BaseStream.Position -= 1;
                    pc = LoadV0(br, gameDll, materialManager);
                    break;
            }
            return pc;
        }

        internal void ToStream(System.IO.BinaryWriter writer)
        {
            try
            {
                writer.Write(VERSION);
                writer.Write(this.streetwidth);
                writer.Write(this.raiRight);
                writer.Write(this.railLeft);
                this.materialForRoad.SaveToStream(writer);
                this.materialForRail.SaveToStream(writer);
                this.traffic.ToStream(writer);
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
        }

        #endregion Internal Methods

        #region Private Methods

        private static PropertiesCR LoadV0(BinaryReader br, Engine.AddinManager.IAddin gameDll, MaterialManager materialManager)
        {
            PropertiesCR pc = new PropertiesCR();
            pc.streetwidth = br.ReadSingle();
            pc.raiRight = br.ReadInt32();
            pc.RailLeft = br.ReadInt32();
            pc.materialForRoad = gameDll.LoadMaterial(br, materialManager);
            pc.materialForRail = gameDll.LoadMaterial(br, materialManager);
            pc.traffic = new CrossroadTraffic(false,
                new CrossroadTrafficData(new Lane(1, 26, -26), 50, 100, 100, true),
                new CrossroadTrafficData(new Lane(1, 26, -26), 50, 100, 100, true),
                new CrossroadTrafficData(new Lane(1, 26, -26), 50, 100, 100, true));
            return pc;
        }

        private static PropertiesCR LoadV1(BinaryReader br, Engine.AddinManager.IAddin gameDll, MaterialManager materialManager)
        {
            PropertiesCR pc = new PropertiesCR();
            pc.streetwidth = br.ReadSingle();
            pc.raiRight = br.ReadInt32();
            pc.RailLeft = br.ReadInt32();
            pc.materialForRoad = gameDll.LoadMaterial(br, materialManager);
            pc.materialForRail = gameDll.LoadMaterial(br, materialManager);
            pc.traffic = new CrossroadTraffic(false,
                new CrossroadTrafficData(new Lane(1, 26, -26), 50, 100, 100, true),
                new CrossroadTrafficData(new Lane(1, 26, -26), 50, 100, 100, true),
                new CrossroadTrafficData(new Lane(1, 26, -26), 50, 100, 100, true));
            return pc;
        }

        private static PropertiesCR LoadV2(BinaryReader br, Engine.AddinManager.IAddin gameDll, MaterialManager materialManager)
        {
            PropertiesCR pc = new PropertiesCR();
            pc.streetwidth = br.ReadSingle();
            pc.raiRight = br.ReadInt32();
            pc.RailLeft = br.ReadInt32();
            pc.materialForRoad = gameDll.LoadMaterial(br, materialManager);
            pc.materialForRail = gameDll.LoadMaterial(br, materialManager);
            pc.traffic = CrossroadTraffic.FromStream(br);

            return pc;
        }

        private static PropertiesCR LoadV3(BinaryReader br, Engine.AddinManager.IAddin gameDll, MaterialManager materialManager)
        {
            // Atm the same as version2 01.02.2017
            PropertiesCR pc = new PropertiesCR();
            pc.streetwidth = br.ReadSingle();
            pc.raiRight = br.ReadInt32();
            pc.RailLeft = br.ReadInt32();
            pc.materialForRoad = gameDll.LoadMaterial(br, materialManager);
            pc.materialForRail = gameDll.LoadMaterial(br, materialManager);
            pc.traffic = CrossroadTraffic.FromStream(br);

            return pc;
        }

        #endregion Private Methods
    }
}